#ifndef LIBAVDECODE_H
#define LIBAVDECODE_H

#include <QObject>
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
#include <QWaitCondition>
#include "EZTally/EZTallyObject.h"
#include "thread/ezqthread.h"
#include "libavDecodeDefine.h"
extern "C"{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
}


class StreamBase;

class LibavDecode : public QObject , public EZTally::EZTallyObject
{
    Q_OBJECT
private:
    friend class EZQThread;
protected:
    ~LibavDecode();
public:
    LibavDecode(int pcmBufSize=1024*8);

private:
    StreamBase *_stream;
    QMutex _streamLock;
    QWaitCondition _streamWaitCondition;

    LibavAutioFormat _audioFormat;

    int _pcmBufSize;
    int _pcmBufLenOil;
    unsigned char *_pcmBuf;
    QMutex _pcmBufLock;
    QWaitCondition _pcmBufWaitCondition;

    int _buffBlockSize;//分块大小
//    int _streamOil;

//    EZQThread *_decodeThread;
    QMutex _decodeMutex;

    uint8_t *_buf;
    AVFormatContext *_formatContext;
    AVIOContext *_ioContext;
    AVCodecContext *_codeContext;
    int _audioIndex;

    bool _willDecode;
//    bool _isStop;
    int _operationIndex;
    QMutex _operationIndexMutex;
    int _curDecodeOperationIndex;

    LibavStatus _decodeStatus;
    void setDecodeStatus(const LibavStatus &decodeStatus);

    int makeoperationIndex();

    void decodeInThread(EZQThread *thread);
    void decode_probe();
    void decode_decode();
    void clearProbe();

    void writePcmBuf(unsigned char *pcm,int size);

    void setAudioFormat(const LibavAutioFormat &audioFormat);

    bool _probeFinish;

    qint64 _seekPos;
    qint64 _duration;
    void setDuration(const qint64 &duration);

private slots:
    void decodeInThreadFinish();
    void onStreamAvailableChange(qint64 offset,qint64 dataLen);
public:
    int contextReadPacket(uint8_t *buf, int buf_size);
    int64_t decodeSeek(int64_t offset, int whence);

    int probeInfo();
    int decode(bool onlyProbe=false);
    void stopDecode();

    StreamBase *stream() const;
    void setStream(StreamBase *stream);
    int buffBlockSize() const;
    void setBuffBlockSize(int buffBlockSize);
    LibavStatus decodeStatus() const;

    int pcmBufSize();
    int readPcmBuf(unsigned char *buffer,int bufferSize);

    LibavAutioFormat audioFormat() const;

    void setSeekPos(const qint64 &pos);
    qint64 duration() const;


signals:
    void sidecodeStateChange(LibavStatus);
    void sidecodePcmAvailableChange();
};

#endif // LIBAVDECODE_H
